package fr.ul.ade.prime.ui;

import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.TextView;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockListFragment;

import fr.ul.ade.R;
import fr.ul.ade.prime.model.AdeWebOptions;
import fr.ul.ade.prime.model.Schedule;
import fr.ul.ade.prime.provider.AdeWebContract;

public class NotifySelectList extends AdeWebFragmentActivity implements
OnClickListener {

	@SuppressWarnings("hiding")
	protected static final String TAG = NotifySelectList.class.getSimpleName();

	// protected NotifyListAdapter adapter ;

	/**
	 * Initialise la vue.
	 * 
	 * @param savedInstanceState
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Fixe le thème de la page
		this.setTheme(AdeWebOptions.getTheme(this));
		// Ajoute un sous-titre à la barre d'action
		ActionBar bar = this.getSupportActionBar();
		bar.setSubtitle(R.string.NotifySelectList_subtitle);
		// Change l'icone de la barre d'action
		bar.setIcon(R.drawable.ic_launch_settings);

		this.setContentView(R.layout.notify_select_list);
	}// onCreate(Bundle)

	/**
	 * Gère le click sur le texte de création d'un emploi du temps affiché
	 * lorsqu'il n'y a pas d'emploi du temps.
	 */
	@Override
	public void onClick(View v) {
		Intent intent = new Intent(this, CreateSchedule.class);
		this.startActivity(intent);
	}// onClick(View)

	public static class NotifyListFragment extends SherlockListFragment
	implements LoaderManager.LoaderCallbacks<Cursor> {

		private NotifyListAdapter mAdapter;

		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			this.mAdapter = new NotifyListAdapter(this.getActivity());
			this.setListAdapter(this.mAdapter);
		}

		@Override
		public void onStart() {
			super.onStart();
			// On récupère le loader
			Loader<Cursor> loader = getLoaderManager().getLoader(
					ScheduleQuery._TOKEN);
			if (loader != null) {
				// On force le rechargment des données.
				loader.forceLoad();
			}
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			return inflater.inflate(R.layout.lesson_list, container, false);
		}

		@Override
		public void onViewCreated(View view, Bundle savedInstanceState) {
			super.onViewCreated(view, savedInstanceState);
			final ListView listView = this.getListView();
			listView.setSelector(android.R.color.transparent);
			listView.setEmptyView(view.findViewById(R.id.empty));
		}

		@Override
		public void onActivityCreated(Bundle savedInstanceState) {
			super.onActivityCreated(savedInstanceState);

			// As of support library r8, calling initLoader for a fragment in a
			// FragmentPagerAdapter in the fragment's onCreate may cause the
			// same LoaderManager to be
			// dealt to multiple fragments because their mIndex is -1 (haven't
			// been added to the
			// activity yet). Thus, we do this in onActivityCreated.

			// On initialise le loader qui s'occupera de charger la liste des
			// edts.
			// Champs :
			// * id du loader (ici il n'y en n'a qu'on donc il n'est pas
			// important)
			// * arguments sous forme d'un Bundle
			// * l'objet qui sera chargé de la création du loader et qui sera
			// averti
			// des changements d'état du loader (chargement terminé ou reset)
			getLoaderManager().initLoader(ScheduleQuery._TOKEN, null, this);
		}

		// On crée le loader, cette fonction est appelée automatiquement par le
		// LoaderManager
		// Dans notre cas, on se contente d'instancier CursorLoader qui est une
		// sous-classe
		// de Loader<Cursor> (charge de manière asynchrone (-> AsyncTask) les
		// données précisés)
		@Override
		public Loader<Cursor> onCreateLoader(int id, Bundle data) {
			Uri scheduleUri = AdeWebContract.Schedule.CONTENT_URI;
			String[] projection = ScheduleQuery.PROJECTION;
			String selection = null;
			String[] selectionArgs = null;
			return new CursorLoader(this.getActivity(), scheduleUri,
					projection, selection, selectionArgs,
					AdeWebContract.Schedule.DEFAULT_SORT);
		}

		// Cette fonction est appelé à chaque fois qu'un loader termine son
		// chargement. Dans notre cas, on se content de passer le nouveau
		// Cursor (qui contient les données) à l'adaptateur qui fera les
		// changements nécessaires dans l'acitivité.
		@Override
		public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
			if (this.getActivity() == null) {
				return;
			}// if
			this.mAdapter.changeCursor(cursor);

			final View view = this.getView();
			view.findViewById(R.id.list_loading).setVisibility(View.GONE);

			this.getView().setBackgroundColor(
					AdeWebOptions.getBackgroundColor(AdeWebOptions
							.getTheme(this.getActivity())));
			if (cursor.getCount() == 0) {
				final LayoutInflater inflater = this.getActivity()
						.getLayoutInflater();
				final ListView listView = this.getListView();
				if (listView.getEmptyView() == null) {
					final View emptyView = inflater.inflate(
							R.layout.lesson_list_empty,
							(ViewGroup) listView.getParent(), true);
					listView.setEmptyView(emptyView);

					final TextView createText = (TextView) emptyView
							.findViewById(R.id.update_schedule);
					createText.setText(R.string.ScheduleList_no_schedule);
					createText.setTextColor(AdeWebOptions
							.getTextColor(AdeWebOptions.getTheme(this
									.getActivity())));
				}// if
			}
		}// onLoadFinished(Loader<Cursor>, Cursor)

		// Cette fonction est appelé à chaque fois que les données d'un
		// loader deviennent inaccessibles. Si on a des références vers
		// ces données, il faut les supprimer.
		@Override
		public void onLoaderReset(Loader<Cursor> loader) {
			/* Nothing to be done. */
		}

		// Un adaptateur classique qui hérite de CursorAdapter (adaptateur qui
		// stocke ces données
		// sous forme d'un cursor).
		private class NotifyListAdapter extends CursorAdapter {

			private Activity mActivity;

			public NotifyListAdapter(Activity activity) {
				super(activity, null, false);
				this.mActivity = activity;
			}

			@Override
			public void bindView(View view, Context context, Cursor cursor) {
				final TextView scheduleName = (TextView) view
						.findViewById(R.id.schedule_name);
				scheduleName.setText(cursor
						.getString(ScheduleQuery.SCHEDULE_NAME));
				//TODO a enlever si recréation de l'activité au changement de thème
				scheduleName
				.setTextColor(AdeWebOptions.getTextColor(AdeWebOptions
						.getTheme(NotifyListFragment.this.getActivity())));

				CheckBox notify = (CheckBox) view
						.findViewById(R.id.schedule_notify);
				notify.setChecked(cursor
						.getInt(ScheduleQuery.SCHEDULE_NOTIFY_UPDATE) == 1);
				final long scheduleId = cursor.getLong(ScheduleQuery._ID);
				// Si la checkbox est cochée ou décochée alors on modifie l'edt
				// en question
				notify.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
					@Override
					public void onCheckedChanged(CompoundButton buttonView,
							boolean isChecked) {
						updateSchedule(scheduleId, isChecked);
					}// onCheckedChanged(CompoundButton, boolean)
				});
			}// bindView

			@Override
			public View newView(Context context, Cursor cursor, ViewGroup parent) {
				return this.mActivity.getLayoutInflater().inflate(
						fr.ul.ade.R.layout.notify_listitem, parent, false);
			}

			/**
			 * Met à jour dans la base de données, la nouvelle valeur du champ
			 * notify de l'emploi du temps selectionné.
			 * 
			 * @param id
			 *            ID de l'emploi du temps
			 * @param notify
			 *            booleen de notification
			 */
			public void updateSchedule(long id, boolean notify) {
				ContentValues values = new ContentValues();
				values.put(AdeWebContract.Schedule.SCHEDULE_NOTIFY_UPDATE,
						Integer.valueOf(notify ? Schedule.NOTIFY_TRUE
								: Schedule.NOTIFY_FALSE));
				this.mActivity.getContentResolver().update(
						ContentUris.withAppendedId(
								AdeWebContract.Schedule.CONTENT_URI, id),
								values, null, null);
			}
		}// NotifyListAdapter

	}// NotifyListFragment

	// Interface auxiliaire utilisé pour les requêtes vers le content provider
	// On retrouve ici les colonnes (données) nécessaires ainsi que des
	// variables
	// auxiliaires pour y accéder.
	public interface ScheduleQuery {
		// id pour le loader
		int _TOKEN = 0x1;

		// colonnes demandées au provider
		String[] PROJECTION = { BaseColumns._ID,
				AdeWebContract.Schedule.SCHEDULE_NAME,
				AdeWebContract.Schedule.SCHEDULE_NOTIFY_UPDATE };

		// colonnes des données demandés pour utiliser lors de la récupération
		// des données depuis le Cursor (appels à getString(int) p.ex.)
		int _ID = 0;
		int SCHEDULE_NAME = 1;
		int SCHEDULE_NOTIFY_UPDATE = 2;
	}// ScheduleQuery

}// class NotifySelectList